<?php

namespace App\Http\Controllers;

use App\Http\Requests\GiveUController\GiveURequest;
use App\Http\Requests\GiveUController\PreNodeRequest;
use App\Jobs\DSE\ReturnDseJob;
use App\Jobs\DSE\ReturnUJob;
use App\Models\Account;
use App\Models\Game;
use App\Models\GameCell;
use App\Models\GameOrder;
use App\Models\GamePreOrder;
use App\Models\Setting;
use App\Models\User;
use Hashids\Hashids;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Xrfg\Core\Trading\Account\Models\Account as TradingAccount;
use Xrfg\Core\Trading\Account\Models\Transfer;

class GameController extends Controller
{
    // 预购节点
    public function preNode(PreNodeRequest $request)
    {
        // 邀请码
        $parent_id = (new Hashids(config('hashids.HASHID_SALT'), config('hashids.HASHID_NUMBER')))->decode($request->input('parent_id'));
        if (!$parent_id || !User::where('id', $parent_id[0])->exists()) {
            $this->error(1116);
        }

        /** @var User $user */
        $user = Auth::user();
        $type = $request->input('type');
        if ($type == 2) { // 购买节点包，判断后台是否开放
                $this->error(30027);
        }

        // 最新游戏状态
        $game = Game::orderByDesc('id')->first();
        if ($type == 2 && $game->node < 20) { // 当前环节点小于20个，不支持购买节点包
            $this->error(30017);
        }
        if ($game->game_status == 0) {
            $this->error(30014);
        }
        if ($game->row_status == 1) {
            $this->error(30018);
        }

        // 邀请码用户，必须购买或预购过节点
        if ($request->input('parent_id') != 'GLO5gD') { // 创世邀请码除外
            if (!GameOrder::where('game_id', $game->id)->where('user_id', $parent_id[0])->exists() && !GamePreOrder::where('game_id', $game->id)->where('user_id', $parent_id[0])->exists()) {
                $this->error(30019);
            }
        }
        // 已预购，不能再预购
        if (GamePreOrder::where('game_id', $game->id)->where('user_id', $user->id)->exists()) {
            $this->error(30020);
        }
        // 已购买过节点，不能再预购
        if (GameOrder::where('game_id', $game->id)->where('user_id', $user->id)->exists()) {
            $this->error(30021);
        }
        // 小节点：100U+10枚DSE质押
        // 节点包：1010U+200枚DSE质押 （一次性拥有20个小节点的收益）
        $usdt_num = 100;
        $dse_num = 10;
        if ($type == 2) { // 购买节点包
            $usdt_num = 1010;
            $dse_num = 200;
        }

        // usdt出账账户
        $usdtOutAccount = TradingAccount::firstOrCreate([
            'user_id' => $user->id,
            'coin_id' => 1,
        ])->refresh();
        if ($usdtOutAccount->available < $usdt_num) {
            $this->error(30005);
        }
        // dse出账账户
        $dseOutAccount = Account::firstOrCreate([
            'user_id' => $user->id,
            'coin_id' => 2,
        ])->refresh();
        if ($dseOutAccount->available < $dse_num) {
            $this->error(30016);
        }

        try {
            DB::transaction(function () use ($game, $usdtOutAccount, $dseOutAccount, $type, $usdt_num, $dse_num, $parent_id) {
                $game = Game::lockForUpdate()->find($game->id);
                $usdtOutAccount = TradingAccount::lockForUpdate()->find($usdtOutAccount->id);
                $dseOutAccount = Account::lockForUpdate()->find($dseOutAccount->id);

                if ($game->game_status ==1 && $game->row_status == 0) {
                    // 1.生成用户预购订单
                    $gameOrder = new GamePreOrder();
                    $gameOrder->user_id = Auth::id();
                    $gameOrder->game_id = $game->id;
                    $gameOrder->type = $type;
                    $gameOrder->parent_id = $parent_id[0];
                    $gameOrder->save();

                    // 2.扣USDT
                    $usdtOutAccount->availableDecrement($usdt_num);
                    $usdtOutAccount->proofId = [$gameOrder->id, 3, 8];
                    $usdtOutAccount->save();

                    // 3.扣DSE
                    $dseOutAccount->availableDecrement($dse_num);
                    $dseOutAccount->disabledIncrement($dse_num);
                    $dseOutAccount->type = '预购';
                    $dseOutAccount->action_id = $gameOrder->id;
                    $dseOutAccount->save();

                    // 返U
                    (new ReturnUJob(1, $gameOrder))->handle();
                }
            });
        } catch (\Exception $exception) {
            Log::error($exception);
            $this->error($exception->getCode());
        }

        return $this->null();
    }

    // 购买节点
    public function buyNode(GiveURequest $request)
    {
        // 邀请码
        $parent_id = (new Hashids(config('hashids.HASHID_SALT'), config('hashids.HASHID_NUMBER')))->decode($request->input('parent_id'));
        if (!$parent_id || !User::where('id', $parent_id[0])->exists()) {
            $this->error(1116);
        }

        /** @var User $user */
        $user = Auth::user();
        $type = $request->input('type');
        if ($type == 2) { // 购买节点包，判断后台是否开放
            if (Setting::where('key', 'is_buy_package')->value('value') != 1) {
                $this->error(30013);
            }
        }

        // 最新游戏状态
        $game = Game::orderByDesc('id')->first();
        if ($type == 2 && $game->node < 20) { // 当前环节点小于20个，不支持购买节点包
            $this->error(30017);
        }
        if ($game->game_status == 0) {
            $this->error(30014);
        }
        if ($game->row_status == 0) {
            $this->error(30015);
        }

        // 邀请码用户，必须购买或预购过节点
        if ($request->input('parent_id') != 'GLO5gD') { // 创世邀请码除外
            if (!GameOrder::where('game_id', $game->id)->where('user_id', $parent_id[0])->exists() && !GamePreOrder::where('game_id', $game->id)->where('user_id', $parent_id[0])->exists()) {
                $this->error(30019);
            }
        }

        $preOrder = GamePreOrder::where('game_id', $game->id)->where('user_id', $user->id)->orderByDesc('type')->first();
        $order = GameOrder::where('game_id', $game->id)->where('user_id', $user->id)->orderByDesc('type')->first();
        $pay = true; // 是否需要支付
        if ($preOrder) {
            if ($preOrder->parent_id != $parent_id[0]) {
                $this->error(30024);
            }
            if ($preOrder->type == 1) { // 预购了节点
                if ($order && $order->type == 2) { // 购买了节点包，不能再买了
                    $this->error(30022);
                }
                if ($order && $order->type == 1 && $type == 1) { // 购买了节点，只能再买节包了
                    $this->error(30023);
                }
                if (!$order && $type == 2) { // 预购了节点，只能购买节点
                    $this->error(30025);
                }
                if (!$order && $type == 1) { // 不需要支付
                    $pay = false;
                }
            }
            if ($preOrder->type == 2) { // 预购了节点包
                if ($order) { // 购买了节点包，不能再买了
                    $this->error(30022);
                }
                if (!$order && $type == 1) { // 预购了节点包，只能购买节点包
                    $this->error(30026);
                }
                if (!$order && $type == 2) { // 不需要支付
                    $pay = false;
                }
            }
        } else {
            if ($order && $order->type == 2) { // 购买了节点包，不能再买了
                $this->error(30022);
            }
            if ($order && $order->type == 1 && $type == 1) { // 购买了节点，只能再买节包了
                $this->error(30023);
            }
            if ($order && $order->parent_id != $parent_id[0]) {
                $this->error(30024);
            }
        }

        // 小节点：100U+10枚DSE质押
        // 节点包：1010U+200枚DSE质押 （一次性拥有20个小节点的收益）
        $usdt_num = 100;
        $dse_num = 10;
        if ($type == 2) { // 购买节点包
            $usdt_num = 1010;
            $dse_num = 200;
        }

        // usdt出账账户
        $usdtOutAccount = TradingAccount::firstOrCreate([
            'user_id' => $user->id,
            'coin_id' => 1,
        ])->refresh();
        if ($pay && $usdtOutAccount->available < $usdt_num) {
            $this->error(30005);
        }
        // dse出账账户
        $dseOutAccount = Account::firstOrCreate([
            'user_id' => $user->id,
            'coin_id' => 2,
        ])->refresh();
        if ($pay && $dseOutAccount->available < $dse_num) {
            $this->error(30016);
        }

        try {
            DB::transaction(function () use ($game, $usdtOutAccount, $dseOutAccount, $type, $usdt_num, $dse_num, $parent_id, $pay) {
                $game = Game::lockForUpdate()->find($game->id);
                $usdtOutAccount = TradingAccount::lockForUpdate()->find($usdtOutAccount->id);
                $dseOutAccount = Account::lockForUpdate()->find($dseOutAccount->id);

                if ($game->game_status ==1 && $game->row_status == 1 && $game->remain_node > 0) {
                    $gameOrder = null;
                    if ($type ==1) { // 购买节点
                        /******************************购买节点 BEGIN*************************************/
                        // 给用户分配节点
                        if ($game->remain_node == 1) { // 节点买完后，需要生成新的环
                            // 1.生成用户订单，当前环最后一个节点分配给用户
                            $gameOrder = new GameOrder();
                            $gameOrder->user_id = Auth::id();
                            $gameOrder->game_id = $game->id;
                            $gameOrder->type = 1;
                            $gameOrder->location = "{$game->current_row}.{$game->node}";
                            $gameOrder->parent_id = $parent_id[0];
                            // 2.生成节点分配记录
                            $gameCell = new GameCell();
                            $gameCell->user_id = Auth::id();
                            $gameCell->game_id = $game->id;
                            $gameCell->row = $game->current_row;
                            $gameCell->col = $game->node;
                            $gameCell->last_row = $game->current_row + 99;
                            // 3.更新环信息
                            $nextRow = Game::getRow($game->current_row + 1);
                            $game->current_row += 1;
                            $game->row_status = 0;
                            $game->node = $nextRow['node'];
                            $game->remain_node = $nextRow['node'];
                            $game->token = $nextRow['token'];
                            $game->price = $nextRow['price'];
                            $game->finish_at = now()->addHours(72);
                            // 4.加环（自己加环，上级加环）
                            $self_add_row = $this->selfAddRow($game->id, Auth::id());// 自己加环
                            $gameCell->last_row += $self_add_row;
                            $gameCell->add_row += $self_add_row;
                            $this->parentAddRow($game->id, $parent_id[0]); // 上级加环

                            $gameOrder->save();
                            $gameCell->save();
                            $game->save();

                            // 环结束结算，返DSE
                            (new ReturnDseJob($game->id, $game->current_row - 1))->handle();
                        } else {
                            // 1.生成用户订单，当前环非最后一个节点分配给用户
                            $gameOrder = new GameOrder();
                            $gameOrder->user_id = Auth::id();
                            $gameOrder->game_id = $game->id;
                            $gameOrder->type = 1;
                            $gameOrder->location = "{$game->current_row}." . ($game->node - $game->remain_node + 1);
                            $gameOrder->parent_id = $parent_id[0];
                            // 2.生成节点分配记录
                            $gameCell = new GameCell();
                            $gameCell->user_id = Auth::id();
                            $gameCell->game_id = $game->id;
                            $gameCell->row = $game->current_row;
                            $gameCell->col = $game->node - $game->remain_node + 1;
                            $gameCell->last_row = $game->current_row + 99;
                            // 3.更新环信息
                            $game->remain_node -= 1;
                            $game->finish_at = now()->addHours(72);
                            // 4.加环（自己加环，上级加环）
                            $self_add_row = $this->selfAddRow($game->id, Auth::id());// 自己加环
                            $gameCell->last_row += $self_add_row;
                            $gameCell->add_row += $self_add_row;
                            $this->parentAddRow($game->id, $parent_id[0]); // 上级加环
                            $gameOrder->save();
                            $gameCell->save();
                            $game->save();
                        }
                        /******************************购买节点 END***************************************/
                    } else if ($type == 2) { // 购买节点包
                        /******************************购买节点包 BEGIN*************************************/
                        if($game->remain_node <= 20){
                            if($game->remain_node == 20 ){
                                $location = "{$game->current_row}." . ($game->node - $game->remain_node + 1)."-{$game->current_row}.{$game->node}";
                            }else{
                                $location = "{$game->current_row}." . ($game->node - $game->remain_node + 1) . "-" . ($game->current_row + 1)."." . (20-$game->remain_node);
                            }
                            // 1.生成用户订单，当前环非最后一个节点分配给用户
                            $gameOrder = new GameOrder();
                            $gameOrder->user_id = Auth::id();
                            $gameOrder->game_id = $game->id;
                            $gameOrder->type = 2;
                            $gameOrder->location = $location;
                            $gameOrder->parent_id = $parent_id[0];
                            // 买完更新游戏状态
                            for ($i=0; $i < 20 ; $i++) { 
                                // 2.生成节点分配记录
                                $gameCell = new GameCell();
                                $gameCell->user_id = Auth::id();
                                $gameCell->game_id = $game->id;
                                $gameCell->row = $game->current_row;
                                $gameCell->col = $game->node - $game->remain_node + 1;
                                $gameCell->last_row = $game->current_row + 99;
                                // 3.更新环信息
                                if($game->remain_node == 1){
                                    $nextRow = Game::getRow($game->current_row + 1);
                                    $game->current_row += 1;
                                    $game->row_status = 0;
                                    $game->node = $nextRow['node'];
                                    $game->remain_node = $nextRow['node'];
                                    $game->token = $nextRow['token'];
                                    $game->price = $nextRow['price'];
                                    $game->finish_at = now()->addHours(72);
                                }else{
                                    $game->remain_node -= 1;
                                    $game->finish_at = now()->addHours(72);
                                }
                                $gameCell->save();
                                $game->save();
                            }
                            $this->parentPackageAddRow($game->id, $parent_id[0]); // 上级加环
                            $gameOrder->save();
                            // 环结束结算，返DSE
                            (new ReturnDseJob($game->id, $game->current_row - 1))->handle();
                        }else if($game->remain_node > 20){
                            // 1.生成用户订单，当前环非最后一个节点分配给用户
                            $gameOrder = new GameOrder();
                            $gameOrder->user_id = Auth::id();
                            $gameOrder->game_id = $game->id;
                            $gameOrder->type = 2;
                            $gameOrder->location = "{$game->current_row}." . ($game->node - $game->remain_node + 1). "-" ."{$game->current_row}.".($game->node - $game->remain_node + 20);
                            $gameOrder->parent_id = $parent_id[0];
                            for ($i=0; $i < 20 ; $i++) { 
                                // 2.生成节点分配记录
                                $gameCell = new GameCell();
                                $gameCell->user_id = Auth::id();
                                $gameCell->game_id = $game->id;
                                $gameCell->row = $game->current_row;
                                $gameCell->col = $game->node - $game->remain_node + 1 + $i;
                                $gameCell->last_row = $game->current_row + 99;
                                $gameCell->save();
                            }
                            $this->parentPackageAddRow($game->id, $parent_id[0]); // 上级加环
                            // 3.更新环信息
                            $game->remain_node -= 20;
                            $game->finish_at = now()->addHours(72);
                            $gameOrder->save();
                            $game->save();
                        }
                        /******************************购买节点包 END***************************************/
                    }

                    // 没有预付订单，需要支付
                    if ($pay) {
                        // 5.扣USDT
                        $usdtOutAccount->availableDecrement($usdt_num);
                        $usdtOutAccount->proofId = [$gameOrder->id, 3, 8];
                        $usdtOutAccount->save();

                        // 6.扣DSE
                        $dseOutAccount->availableDecrement($dse_num);
                        $dseOutAccount->disabledIncrement($dse_num);
                        $dseOutAccount->type = '质押';
                        $dseOutAccount->action_id = $gameOrder->id;
                        $dseOutAccount->save();

                        // 返U
                        (new ReturnUJob(2, $gameOrder))->handle();
                    }
                }
            });
        } catch (\Exception $exception) {
            Log::error($exception);
            $this->error($exception->getCode());
        }

        return $this->null();
    }

    // 团队列表
    public function teamList(Request $request)
    {
        $game = Game::orderByDesc('id')->first();
        $user_ids = User::recomendCount(Auth::id());
        $list = [];
        foreach ($user_ids as $user_id) {
            $user = User::find($user_id);
            $location = '';
            GameOrder::where('game_id', $game->id)->where('user_id', $user->id)->get()->each(function ($order) use (&$location) {
                $location .= ' ' . $order->location;
            });
            $list[] = [
                'location' => $location,
                'invite' => (new Hashids(config('hashids.HASHID_SALT'), config('hashids.HASHID_NUMBER')))->encode($user->id),
                'username' => $user->username,
                'node_num' => GameCell::where('game_id', $game->id)->where('user_id', $user->id)->count()
            ];
        }
       // GameOrder::where('parent_id', Auth::id())->where('game_id', $game->id)->select('user_id')->distinct()->get()->each(function ($user) use (&$list, $game) {

       // });

        return $this->array($list);
    }

    // 节点详情
    public function nodeDetail(Request $request)
    {
        $game = Game::orderByDesc('id')->first();
        // 当前环售卖百分比
        $percent = bcadd(($game->node - $game->remain_node) / $game->node, 0, 2);
        // 节点达人赛
        $node_pool = GameCell::where('game_id', $game->id)->whereDate('created_at', today())->count() * 1;
        // 统计前3名
        $parent_ids = GameOrder::where('game_id', $game->id)->whereDate('created_at', today())->select('parent_id')->distinct()->get();
        $arr = [];
        foreach ($parent_ids as $parent_id) {
            $num = 0;
            GameOrder::where('game_id', $game->id)->whereDate('created_at', today())->where('parent_id', $parent_id->parent_id)->get()->each(function ($order) use (&$num) {
                $num += ($order->type == 1) ? 1 : 20;
            });
            $arr[$parent_id->parent_id]['num'] = $num;
        }
        $arr = collect($arr)->sortByDesc('num')->take(3)->toArray();
        $rank = [];
        $k = 0;
        foreach ($arr as $key => $val) {
            $k++;
            if ($k == 1) {
                $reward = bcmul($node_pool, 0.5, 2);
            } else if ($k == 2) {
                $reward = bcmul($node_pool, 0.3, 2);
            } else if ($k == 3) {
                $reward = bcmul($node_pool, 0.2, 2);
            } else {
                $reward = 0;
            }
             $rank[] = [
                'rank' => $k,
                 'username' => User::find($key)->username,
                 'num' => $val['num'],
                 'reward' => $reward
             ];
        }
        // 末日风暴
        $end_pool = GameCell::where('game_id', $game->id)->count();
        $end_1 = 0; // 最后一名
        if ($end_pool > 0) {
            if ($game->node == $game->remain_node) { // 最后一环，一个节点都没有卖出, 取上一环
                $preRow = Game::getRow($game->current_row - 1);
                $end_1 = bcdiv($end_pool * 0.5, $preRow['node'], 2);
            } else {
                $end_1 = bcdiv($end_pool * 0.5, $game->node - $game->remain_node, 2);
            }
        }
        $end_2 = $end_pool * 0.5; // 最后一层
        $end_3 = $end_pool; // 倒数100层所有节点

        return $this->array([
            'row_status' => $game->row_status,
            'percent' => $percent,
            'token' => bcadd($game->token, 0, 6),
            'price' => bcadd($game->price, 0, 2),
            'total_node' => GameCell::count(),
            'total_token' => $this->totalToken($game->current_row - 1),
            'total_withdraw' => bcadd(Transfer::sum('number'), 0, 4),
            'node_pool' => $node_pool,
            'rank' => $rank,
            'end_pool' => $end_pool,
            'end_1' => $end_1,
            'end_2' => $end_2,
            'end_3' => $end_3,
            'end_second' => strtotime($game->finish_at) - now()->timestamp,
            'current_row' => $game->current_row,
            'remain_node' => $game->current_row . '.' . ($game->node - $game->remain_node + 1) . '-' . $game->current_row . '.' . $game->node
        ]);
    }

    // 统计累计产出DSE
    public function totalToken($row)
    {
        $token = 0;
        for ($i = 1; $i <= $row; $i++) {
            $r = Game::getRow($i);
            $token += $r['token'];
        }
        return $token;
    }

    // 购买节点时，计算自己应该增加的环数
    public function selfAddRow($game_id, $user_id)
    {
        $row = 0;
        $preOrder = GamePreOrder::where('game_id', $game_id)->where('user_id', $user_id)->first();
        if ($preOrder) {
            $order = GameOrder::where('game_id', $game_id)->where('user_id', $user_id)->first();
            if (!$order) { // 统计在预购期间，共邀请用户购买节点获得的环数奖励
                $node = GameOrder::where('game_id', $game_id)->where('parent_id', $user_id)->where('type', 1)->count(); // 邀请人购买节点个数
                $package = GameOrder::where('game_id', $game_id)->where('parent_id', $user_id)->where('type', 2)->count(); // 邀请人购买节点包个数
                $row = $node * 3 + $package * 90;
            }
        }

        return $row;
    }

    // 购买节点时，给上级增加3环
    public function parentAddRow($game_id, $parent_id)
    {
        $current_row = Game::where('id', $game_id)->value('current_row');
        $cell = GameCell::where('game_id', $game_id)->where('user_id', $parent_id)->get();
        $count = count($cell);
        if ($count == 1 || $count == 20) { // 只购买了节点 或 只购买了节点包
            if ($cell[0]->last_row >= $current_row) {
                $cell[0]->last_row += 3;
            } else {
                $cell[0]->last_row = $current_row + 2;
            }
            $cell[0]->add_row += 3;
            $cell[0]->save();
        }
        if ($count == 21) { // 先购买了节点，再购买了节点包
            if ($cell[1]->last_row >= $current_row) {
                $cell[1]->last_row += 3;
            } else {
                $cell[1]->last_row = $current_row + 2;
            }
            $cell[1]->add_row += 3;
            $cell[1]->save();
        }
    }

    // 购买节点包时，计算自己应该增加的环数
    public function selfPackageAddRow()
    {
        $node1 = 0;
        $node2 = 0;
        $node3 = 0;
        $node4 = 0;
        $node5 = 0;
        $node6 = 0;
        $node7 = 0;
        $node8 = 0;
        $node9 = 0;
        $node10 = 0;
        $node11 = 0;
        $node12 = 0;
        $node13 = 0;
        $node14 = 0;
        $node15 = 0;
        $node16 = 0;
        $node17 = 0;
        $node18 = 0;
        $node19 = 0;
        $node20 = 0;
        return [
            $node1,$node2,$node3,$node4,$node5,$node6,$node7,$node8,$node9,$node10,$node11,$node12,$node13,$node14,$node15,$node16,$node17,$node18,$node19,$node20
        ];
    }

    // 购买节点包时，给上级增加90环
    public function parentPackageAddRow($game_id, $parent_id)
    {
        $current_row = Game::where('id', $game_id)->value('current_row');
        $cell = GameCell::where('game_id', $game_id)->where('user_id', $parent_id)->get();
        $count = count($cell);
        if($count == 1){
            if ($cell[0]->last_row >= $current_row) {
                $cell[0]->last_row += 90;
            } else {
                $cell[0]->last_row = $current_row + 89;
            }
            $cell[0]->add_row += 90;
            $cell[0]->save();
        }
        if($count == 20){
            foreach ($cell as $key => $value) {
                if ($key == 19){
                    if ($cell[$key]->last_row >= $current_row) {
                        $cell[$key]->last_row += 33;
                    } else {        
                        $cell[$key]->last_row = $current_row + 32;
                    }
                    $cell[$key]->add_row += 33;
                    $cell[$key]->save();
                }else{
                    if ($cell[$key]->last_row >= $current_row) {
                        $cell[$key]->last_row += 3;
                    } else {        
                        $cell[$key]->last_row = $current_row + 2;
                    }
                    $cell[$key]->add_row += 3;
                    $cell[$key]->save(); 
                }
            }
        }
        if($count == 21){
            foreach ($cell as $key => $value) {
                if ($key == 20){
                    if ($cell[$key+1]->last_row >= $current_row) {
                        $cell[$key+1]->last_row += 33;
                    } else {        
                        $cell[$key+1]->last_row = $current_row + 32;
                    }
                    $cell[$key+1]->add_row += 33;
                    $cell[$key+1]->save();
                }else{
                    if ($cell[$key+1]->last_row >= $current_row) {
                        $cell[$key+1]->last_row += 3;
                    } else {        
                        $cell[$key+1]->last_row = $current_row + 2;
                    }
                    $cell[$key+1]->add_row += 3;
                    $cell[$key+1]->save(); 
                }
            }
        }
    }
}
